# -*- coding:utf-8 -*-

"""
version: 1.00.00
change:
"""

import thread

from MyException import NoKeyError

#互斥字典定义
class MutexMap:
    def __init__(self):
        """
        初始化
        """
        self.object_map = {}
        self.mutex_lock = thread.allocate_lock()
        
    def insert(self, key, value):
        """
        向字典中怎家一个元素，如果key不存在，则添加该元素，如果key已经存在则更新value值
        @param key: 键，数据类型可以是integer或string
        @param value: 值，数据类型任意
        """
        self.mutex_lock.acquire()
        self.object_map[key] = value
        self.mutex_lock.release()
        
    def find(self, key):
        """
        根据key在字典中查找value，如果key存在则返回对应的值，如果不存在则返回None
        @param key: 键
        @return: key所对应的value，或None
        """
        self.mutex_lock.acquire()
        
        try:
            try:
                value = self.object_map[key]
            except Exception, msg:
                raise NoKeyError("not find file " + key)
        finally:
            self.mutex_lock.release()
            
        return value
        
    def delete(self, key):
        """
        根据key值从字典中删除key和value，如果key不存在则不做任何处理
        @param key: 键
        """
        self.mutex_lock.acquire()
        try:
            try:
                del self.object_map[key]
            except Exception, msg:
                raise NoKeyError("not find file " + key)
        finally:
            self.mutex_lock.release()
    
    def _show(self):
        """
        输出字典中所有内容,key和value强制转换成string数据类型
        """
        print ", ".join(["(" + str(key) + ", " + str(self.object_map[key]) + ")" for key in self.object_map.keys()])
        
#单元测试
import unittest
import time

class MutexMapTestCase(unittest.TestCase):
    def setUp(self):
        self.mutex_map = MutexMap()
        self.mutex_map._show()
    
    def tearDown(self):
        pass
    
    def test_insert(self):
        print "----test insert----"
        self.mutex_map.insert(1, 1)
        self.mutex_map.insert(2, 2)
        self.mutex_map._show()
        
    def test_find(self):
        print "----test find----"
        self.mutex_map.insert(1, 1)
        self.mutex_map.insert(2, 2)
        self.mutex_map._show()
        print "find (2) :", self.mutex_map.find(2)
        
    def test_delete(self):
        print "----test delete----"
        self.mutex_map.insert(1, 1)
        self.mutex_map.insert(2, 2)
        self.mutex_map._show()
        print "delete (2)"
        self.mutex_map.delete(2)
        self.mutex_map._show()
        
    def test_thread(self):
        print "----test thread----"
        thread.start_new(self.producer, ())
        thread.start_new(self.spectator, ())
        thread.start_new(self.customer, ())
        time.sleep(30)
        
    def producer(self):
        count = 1
        while True:
            self.mutex_map.insert(count, count)
            count += 1
            time.sleep(4)
        
    def spectator(self):
        while True:
            self.mutex_map._show()
            time.sleep(3)
            
    def customer(self):
        count = 1
        while True:
            time.sleep(8)
            self.mutex_map.delete(count)
            count += 1
            
if __name__ == "__main__":
    suite = unittest.TestSuite()
    suite.addTest(MutexMapTestCase("test_insert"))
    suite.addTest(MutexMapTestCase("test_find"))
    suite.addTest(MutexMapTestCase("test_delete"))
    suite.addTest(MutexMapTestCase("test_thread"))
    
    runner = unittest.TextTestRunner()
    runner.run(suite)
        
        